import Docker from 'dockerode';
import { DockerImageInfo, ContainerInfo } from './types/docker';

export class DockerTool {
  private docker: Docker;

  constructor() {
    this.docker = new Docker();
  }

  async listImages(): Promise<DockerImageInfo[]> {
    const images = await this.docker.listImages();
    const result: DockerImageInfo[] = images.flatMap((image) => {
      const repoTags = image.RepoTags || ['<none>:<none>'];
      return repoTags.map((tag) => {
        const [repository = '<None>', tagName = '<None>'] = tag.split(':');
        return {
          REPOSITORY: repository === '<none>' ? undefined : repository,
          TAG: tagName,
          IMAGE_ID: image.Id,
          CREATED: image.Created,
          SIZE: image.Size,
        };
      });
    });
    return result;
  }

  async listRunningContainers(): Promise<ContainerInfo[]> {
    const containers = await this.docker.listContainers({ all: true });
    console.log('Running containers:', containers);
    return containers.map((container) => ({
      CONTAINER_ID: container.Id,
      IMAGE: container.Image,
      COMMAND: container.Command,
      CREATED: container.Created,
      STATUS: container.Status,
      PORTS: container.Ports.map(
        (p) => `${p.IP}:${p.PublicPort}->${p.PrivatePort}/${p.Type}`,
      ).join(', '),
      NAMES: container.Names.join(', '),
    }));
  }

  async startContainer(containerIdOrName: string): Promise<void> {
    const container = this.docker.getContainer(containerIdOrName);
    await container.start();
    console.log(`Container ${containerIdOrName} started.`);
  }

  async runNewContainer(
    imageName: string,
    options: Docker.ContainerCreateOptions = {},
  ): Promise<void> {
    const container = await this.docker.createContainer({
      Image: imageName,
      ...options,
    });
    await container.start();
    console.log(`New container from image ${imageName} started.`);
  }

  async deleteImage(imageIdOrName: string, force: boolean = true): Promise<void> {
    try {
      const image = this.docker.getImage(imageIdOrName);
      await image.remove({ force });
      console.log(`Image ${imageIdOrName} deleted.`);
    } catch (error) {
      console.error(`Failed to delete image ${imageIdOrName}:`, error);
      throw error;
    }
  }
}
